<template>
  <div class="flowEdit">
    <div id="stencil"></div>
    <div class="right">
      <toolbar @saveClick="saveClick" @zoomIn="zoomIn" @zoomOut="zoomOut" @undo="undo" @redo="redo" @del="del" @copy="copy" @paste="paste" @originalScale="originalScale" :isDisabledBtn="isDisabledBtn"></toolbar>
      <div id="graph"></div>
    </div>
    <div id="minMap"></div>
    <!-- <configPanel :drawer.sync="drawer" @saveConfig="saveConfig" :configData="configData" :currentTargetNodePortId="currentTargetNodePortId"></configPanel> -->
    <!-- 设置的弹窗 -->
    <configDialog :visible.sync="visible" @close="close" @submit="submit" :configData="configData"></configDialog>
  </div>
</template>

<script>
import { deepClone } from '@/utils'
import '@antv/x6-vue-shape'
// import { rectInterface } from './shape'
import configPanel from './compontents/configPanel'
import toolbar from './compontents/toolbar'
import FlowGraph from './compontents/flowGraph'
import FlowGraphEngine from './compontents/flowGraph/engine'
import configDialog from './compontents/configDialog'
import { optionList, compareMap } from './data'
import operateMixin from './operateMixin'
// import dropdown from './dropdown'

export default {
  name: 'flowEdit',
  mixins: [operateMixin],
  components: {
    configPanel,
    toolbar,
    configDialog
    // dropdown
  },
  props: {
    portData: {
      type: Array,
      default: () => []
    },
    flowData: {
      type: Object,
      default: () => null
    }
  },
  data() {
    return {
      visible: false,
      graph: null,
      stencil: null,
      drawer: false,
      tipShow: false,
      isDisabledBtn: {
        canUndo: false,
        canRedo: false,
        canDel: false,
        canCopy: false,
        canPaste: false,
        canSave: false
      },
      // 连线的配置项数据
      configData: {},
      currentTargetNodePortId: '',
      stencilData: null,
      // 新增的node节点
      node: null,
      isAdd: true
    }
  },
  computed: {},
  watch: {
    portData: {
      handler(val) {
        // const formatePortDataList = this.formatePortDataList(val)
        // 加载物料区
        this.flowGraph.createNodeStencil(val)
      }
    },
    flowData: {
      handler(val) {
        // 渲染画布区
        val && this.flowGraph.graphRender(val)
      }
    }
  },
  mounted() {
    this.flowGraphInit()
  },
  methods: {
    // 初始化流程图
    /**
     * 流程组
     */
    flowGraphInit() {
      // 规则引擎
      this.flowGraph = new FlowGraphEngine({
        // 流程图业务数据
        graphData: this.flowData,
        // 流程图物料区数据
        stencilData: this.stencilData,
        // 按钮状态
        isDisabledBtn: this.isDisabledBtn
      })
      this.flowGraph.graph.cleanHistory()
      this.flowGraph.graph.history.on('change', ev => {
        this.isDisabledBtn.canUndo = this.flowGraph.graph.history.canUndo()
        this.isDisabledBtn.canRedo = this.flowGraph.graph.history.canRedo()
      })
      // 所有事件
      this.eventCollection()
    },

    // 保存配置项
    saveConfig(data) {
      const currentCells = this.flowGraph.graph.getSelectedCells()
      currentCells[0].store.data.configData = data
    },
    // 保存前需要进行校验
    saveVerfiy() {
      return new Promise(resolve => {
        const getRootNodes = this.flowGraph.graph.getRootNodes()
        // console.log(getRootNodes, '===getRootNodes==')
        if (getRootNodes.length > 1) {
          // 画布只能有一个节点，且节点是开始投保 ，开始投保也必须有连出线
          this.$message.error('画布只能有一个根节点')
          //
        } else {
          const getOutgoingEdges = this.flowGraph.graph.getOutgoingEdges(getRootNodes[0])
          if (!!getOutgoingEdges) {
            resolve('success')
          } else {
            this.$message.error('流程必须从“开始投保”开始')
          }

          // if (getRootNodes[0].store.data.type !== 'page') {
          //   this.$message.error('画布根节点只能是页面')
          // } else {
          //   resolve('success')
          // }
        }
      })
    },
    // 保存数据
    async saveClick() {
      // 校验画布里面只能有一个留存图，及只能有一个根节点
      // const res = await this.saveVerfiy()
      // if (res === 'success') {
        const flowData = this.flowGraph.graph.toJSON()
        const data = {
          flowData,
          formateData: this.getFormateData(flowData.cells)
        }
        console.log(data, '===data===')
        this.$emit('saveClick', data)
      // }
    },
    // 保存按钮置灰
    saveBtnDisabled() {
      this.isDisabledBtn.canSave = false
    },
    // 控制连接桩显示/隐藏
    showPorts(ports, show) {
      for (let i = 0, len = ports.length; i < len; i = i + 1) {
        ports[i].style.visibility = show ? 'visible' : 'hidden'
      }
    },

    // 事件
    eventCollection() {
      this.flowGraph.graph.on('node:mouseenter', ({ node }) => {
        // console.log(node, '===node--')
        const container = document.getElementById('graph')
        const ports = container.querySelectorAll('.x6-port-body')
        this.showPorts(ports, true)
        if (node.store.data.type !== 'start') {
          node.addTools([
            {
              name: 'button-remove',
              args: { x: 5, y: 5 }
            }
          ])
        }
      })
      this.flowGraph.graph.on('node:mouseleave', ({ cell, node }) => {
        const container = document.getElementById('graph')
        const ports = container.querySelectorAll('.x6-port-body')
        this.showPorts(ports, false)
        if (node.hasTool('button-remove')) {
          node.removeTool('button-remove')
        }
        node.zIndex = 2
      })
      this.flowGraph.graph.on('node:click', ({ node }) => {
        if (node.hasTool('button-remove')) {
          node.removeTool('button-remove')
        }
        if (node?.store?.data?.type !== 'property') {
          this.visible = true

          this.configData = deepClone(node?.store?.data?.configData)
        }
        this.isAdd = false
      })
      // this.flowGraph.graph.on('edge:click', ev => {
      //   // 获取点击edge的起点node id
      //   const sourceNodeId = ev.cell.store.data.source.cell
      //   // 获取所有节点数据
      //   const getNodesData = this.flowGraph.graph.model.getNodes()
      //   // // 获取起点node数据
      //   const currentTargetNode = getNodesData.find(item => item.store?.data?.id === sourceNodeId)
      //   if (currentTargetNode.store.data.type === 'interface') {
      //     this.drawer = true
      //     this.configData = ev.cell?.store?.data?.configData || null
      //     this.currentTargetNodePortId = currentTargetNode.store.data?.data?.id
      //   } else {
      //     this.$message.error('没有配置项')
      //   }
      // })
      this.flowGraph.graph.on('edge:mouseenter', ev => {
        // 连线属性
        ev.cell.setAttrs({
          line: {
            stroke: '#409EFF'
          }
        })
        ev.cell.zIndex = 1

        const { pageX, pageY } = ev.e
        this.position = {
          x: pageX,
          y: pageY
        }

        this.tipShow = true
        ev.cell.addTools([
          {
            name: 'button-remove',
            args: {
              x: '100%',
              y: 0,
              offset: {
                x: 0,
                y: 0
              }
            }
          }
        ])
        // console.log(this.position, ev, '==position==')
      })
      this.flowGraph.graph.on('edge:mouseleave', ev => {
        // 连线属性
        ev.cell.setAttrs({
          line: {
            stroke: '#A2B1C3'
          }
        })
        ev.cell.zIndex = 0

        const { pageX, pageY } = ev.e
        this.position = {
          x: pageX,
          y: pageY
        }
        this.tipShow = false

        if (ev.cell.hasTool('button-remove')) {
          ev.cell.removeTool('button-remove')
        }
      }),
        this.flowGraph.graph.on('selection:changed', cell => {
          // code here
          const { selected } = cell
          this.isDisabledBtn.canCopy = selected.length > 0
          this.isDisabledBtn.canDel = selected.length > 0
        })
      // 双击页面修改名称
      this.flowGraph.graph.on('node:dblclick', ({ node, e }) => {
        // console.log(node, '==node===')
        if (node.store.data.type === 'page') {
          node.addTools({
            name: 'node-editor',
            args: {
              event: e
            }
          })
        }
      })
      // 监听所有cell的属性改变
      this.flowGraph.graph.on('cell:change:*', () => {
        // this.isDisabled
        this.isDisabledBtn.canSave = true
      }),
        this.flowGraph.graph.on('node:added', ({ node }) => {
          if (node.store.data.type === 'conditions' || node.store.data.type === 'result') {
            this.visible = true
            this.node = node
            this.isAdd = true
          }
        })
    },

    // 关闭删除当前节点
    close() {
      if (this.isAdd) {
        this.flowGraph.graph.removeNode(this.node)
      }
      this.configData = {}
    },
    // 提交时候，修改数据
    setSubmitData(data) {
      const { type } = data
      if (type === '0') {
        data.compareList = [{ compare: '', compareValue: '' }]
      } else {
        data.regular = ''
      }
      return data
    },
    // 数据提交
    submit(val) {
      this.node.setAttrs({
        label: { text: this.setNodeAttr(val).text }
      })
      this.node.setProp({
        size: {
          width: this.setNodeAttr(val).width
        }
      })
      this.$set(this.node.store.data, 'configData', this.setSubmitData(val))
      this.configData = {}
    },

    /**
     * 根据数据渲染节点显示的字段和宽度
     */

    /**
     * 文字的像素宽度
     */
    getLenPx(str, font_size) {
      var str_leng = str.replace(/[^\x00-\xff]/gi, 'aa').length
      return (str_leng * font_size) / 2 + 10
    },

    setNodeAttr(data) {
      const { compareList = null, regular = null, type } = data
      const title = optionList.find(item => item.value === type)?.label
      const compareListText = compareList
        .map(item => {
          return compareMap[item.compare] + item.compareValue
        })
        ?.join('或')
      const content = type === '0' ? regular : compareListText
      const width = this.getLenPx(`${title}: ${content}`, 12)
      return {
        text: `${title}: ${content}`,
        width
      }
    },

    /**
     * 格式化业务数据
     * 后端所需数据格式
     */
    getFormateData(data) {
      // const {nodes, edges} = getNodesAndEdges
      const getNodes = data.filter(item => item.shape === 'custom-rect')
      const getEdges = data.filter(item => item.shape === 'edge')
      // console.log(getNodes, getEdges, '===getEdges=')
      let targetNodes = []
      getEdges.forEach(item => {
        // target Id
        const targetNodeId = item.target.cell
        const sourceNodeId = item.source.cell
        const configData = item?.configData ? item.configData : []
        const targetNode = getNodes.find(n => n.id === targetNodeId)
        const sourceNode = getNodes.find(n => n.id === sourceNodeId)
        targetNodes.push({
          parentWebId: sourceNodeId,
          webId: targetNodeId,
          // parentId: sourceNode?.data?.id || '100', // '上级id 100 为第一层级',
          portId: targetNode?.data?.id, // '接口ID',
          flowRequestType: targetNode.type, // '1 接口 2页面',
          condition: configData,
          // isRootNode: sourceNode.type === 'start' ? 'Y' : 'N'
        })
      })
      return targetNodes
    }
  }
}
</script>

<style lang="scss" scoped>
.flowEdit {
  display: flex;
  border: 1px solid #dfe3e8;
  height: calc(100vh - 84px);
  width: 100%;
}
.tooltip {
  position: fixed;
  z-index: 9999;
}
</style>